/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "file_type_parser_default.h"
#include "log.h"
#include "securec.h"
#include "utils/file_type_util.h"

namespace ImageKnifePro {

void DecodeImageSourceDefault::CreateDecoderAvif()
{
    if (buffer_ == nullptr || length_ == 0) {
        return;
    }

    ImageKnifeDecoderAvif *decoder = new ImageKnifeDecoderAvif;
    std::string errorInfo = decoder->Init(buffer_, length_);
    if (errorInfo.empty()) {
        avifDecoder_ = decoder;
    } else {
        delete decoder;
        IMAGE_KNIFE_LOG(LOG_ERROR, "create Avif decoder error:%{public}s", errorInfo.c_str());
    }
}

ImageKnifeDecoderAvif *DecodeImageSourceDefault::GetAvifDecoder() const
{
    return avifDecoder_;
}

DecodeImageSourceDefault::DecodeImageSourceDefault(uint8_t *buffer, uint32_t length) : buffer_(buffer), length_(length)
{
}

void DecodeImageSourceDefault::CreateImageSourceNative()
{
    if (imageSource_ == nullptr) {
        auto errorCode = OH_ImageSourceNative_CreateFromData(buffer_, length_, &imageSource_);
        if (errorCode != IMAGE_SUCCESS) {
            errorInfo_ = "Create ImageSourceNative Failed:" + std::to_string(errorCode);
            imageSource_ = nullptr;
        }
    }
}

DecodeImageSourceDefault::~DecodeImageSourceDefault()
{
    if (imageSource_ != nullptr) {
        OH_ImageSourceNative_Release(imageSource_);
    }

    if (avifDecoder_ != nullptr) {
        delete avifDecoder_;
    }
}

std::string DecodeImageSourceDefault::GetErrorInfo() const
{
    return errorInfo_;
}

OH_ImageSourceNative *DecodeImageSourceDefault::GetImageSourceNative() const
{
    return imageSource_;
}

FileTypeParserDefault &FileTypeParserDefault::GetInstance()
{
    static FileTypeParserDefault fileTypeParser;
    return fileTypeParser;
}

std::shared_ptr<FileTypeInfo> FileTypeParserDefault::ParseFileTypeInfo(uint8_t *buffer, uint32_t length,
                                                                       std::shared_ptr<DecodeImageSource> imageSource)
{
    auto fileTypeInfo = std::make_shared<FileTypeInfo>();
    fileTypeInfo->format = FileTypeUtil::CheckImageFormat(buffer, length);
    if (fileTypeInfo->format == ImageFormat::UNKNOWN) {
        return fileTypeInfo;
    }

    auto imageSourceDefault = std::dynamic_pointer_cast<DecodeImageSourceDefault>(imageSource);
    if (imageSourceDefault == nullptr) {
        return fileTypeInfo;
    }

    if (fileTypeInfo->format == ImageFormat::AVIF) {
        imageSourceDefault->CreateDecoderAvif();
        GetImageFileInfoFromAvifDecoder(fileTypeInfo.get(), imageSourceDefault->GetAvifDecoder());
    } else {
        imageSourceDefault->CreateImageSourceNative();
        GetImageFileInfoFromSource(fileTypeInfo.get(), imageSourceDefault->GetImageSourceNative());
    }

    return fileTypeInfo;
}

void FileTypeParserDefault::GetImageFileInfoFromAvifDecoder(FileTypeInfo *fileTypeInfo, ImageKnifeDecoderAvif *decoder)
{
    if (decoder == nullptr) {
        return;
    }

    fileTypeInfo->frameCount = decoder->GetFrameCount();
    fileTypeInfo->width = decoder->GetWidth();
    fileTypeInfo->height = decoder->GetHeight();
    fileTypeInfo->delayTimeList = decoder->GetDelayTimeList();
}

void FileTypeParserDefault::GetImageFileInfoFromSource(FileTypeInfo *fileTypeInfo, OH_ImageSourceNative *source)
{
    if (source == nullptr) {
        return;
    }

    // 创建定义图片信息的结构体对象，并获取图片信息
    OH_ImageSource_Info *imageInfo;
    OH_ImageSourceInfo_Create(&imageInfo);
    auto imgErrorCode = OH_ImageSourceNative_GetImageInfo(source, 0, imageInfo);
    if (imgErrorCode != IMAGE_SUCCESS) {
        IMAGE_KNIFE_LOG(LOG_ERROR, "ImageSourceNative Get ImageInfo Failed: %{public}d", imgErrorCode);
        return;
    }

    OH_ImageSourceInfo_GetWidth(imageInfo, &fileTypeInfo->width);
    OH_ImageSourceInfo_GetHeight(imageInfo, &fileTypeInfo->height);
    OH_ImageSourceInfo_Release(imageInfo);

    imgErrorCode = OH_ImageSourceNative_GetFrameCount(source, &fileTypeInfo->frameCount);
    if (imgErrorCode != IMAGE_SUCCESS) {
        IMAGE_KNIFE_LOG(LOG_ERROR, "ImageSourceNative Get FrameCount Failed: %{public}d", imgErrorCode);
        fileTypeInfo->frameCount = 0;
        return;
    }

    if (fileTypeInfo->frameCount > 1) {
        int *delayTimeList = new int[fileTypeInfo->frameCount];
        imgErrorCode = OH_ImageSourceNative_GetDelayTimeList(source, delayTimeList, fileTypeInfo->frameCount);
        if (imgErrorCode != IMAGE_SUCCESS) {
            IMAGE_KNIFE_LOG(LOG_ERROR, "ImageSourceNative Get DelayTimeList Failed: %{public}d", imgErrorCode);
            delete [] delayTimeList;
            return;
        }

        auto deleter = [](void *data) {
            int *timeList = static_cast<int *>(data);
            delete [] timeList;
        };
        fileTypeInfo->delayTimeList = std::shared_ptr<int []>(delayTimeList, deleter);
    }
}

std::shared_ptr<DecodeImageSource> FileTypeParser::CreateDecodeImageSource(uint8_t *buffer, uint32_t length)
{
    return nullptr;
}

}